#!/usr/bin/python

import sys
import shutil
import re
import zutil

#shutil.copy("token.h", "yyytoken.h")

s_tokens_prefix = r"""
                                                                        \
  /* Z: Keywords. */                                                    \
  /* Must be after js tokens. Token END must come first */              \
"""

tokens = ["end", "elif"]

def gen_token_str(s_token,pad=0):
    #   K(END, "end", 0)     
    s = "  K(" + s_token.upper() + ", \"" + s_token + "\", 0)"
    if pad != 0:
        s = s.ljust(pad) + "\\" + "\n"
    return s


def update_tokenh():
    """ Update the token.h file. 
        Update the TOKEN_LIST macro with new zed tokens.
        
        Use the following string as the 'final' token after which the 
        new zed tokens should appended:
      T(COMMENT, NULL, 0)                                                \
      
      The following text is dynamically generated using the 
      python list 'tokens':-
      
  /* Z: Keywords. */                                                    \
  /* Must be after js tokens. Token END must come first */              \
  K(END, end, 0)                                                        \
  K(ELIF, elif, 0)
    """

    # filename
    s_filename = "token.h"
    
    # read the file
    f = open(zutil.get_read_path(s_filename))
    s_file = f.read() 
    f.close()

    #Get the line length using the EOS token
    p = re.compile(r"^\s*T\(EOS.*\\$", re.MULTILINE)
    m = p.search(s_file)
    if not m:
        raise Exception("No match for EOS token found")
    s_eos = m.group()
    line_length = len(s_eos) - 1 # -1 for the backslash
    
    # assume WHITESPACE is final token 
    # - throw error if not (ie has a trailing backslash)
    p = re.compile(r"^.*T\(WHITESPACE.*$", re.MULTILINE)
    m = p.search(s_file)
    if not m:
        raise Exception("No match for *last* COMMENT token found")
    #print m
    #print m.group()
    #print m.start(), m.end()
    s_comment = m.group()
    if s_comment.endswith("\\"):
        raise Exception("COMMENT has a trailing \\ - error is not last token")
        
    # add a backslash to comment 
    s_comment_slash = s_comment.ljust(line_length) + "\\"
    #print s_comment_slash
    
    # add the zed tokens to the token list macro
    s_tokens = ""
    pad = 0 # used for padding the token with the final backslash
            # 0 indicates last token thus no padding/backslash required
    for i, s_token in enumerate(tokens):
        if len(tokens)-1 == i : pad = 0
        else : pad = line_length
        s_tokens += gen_token_str(s_token, pad)
    
    s_add = s_comment_slash + s_tokens_prefix + s_tokens
    #print s_add
    
    # replace the original comment line with the new token string s_add
    s_file = p.sub(s_add, s_file)
    #print s_file
    
    # write the file
    f = open(zutil.get_write_path(s_filename), "w")
    f.write(s_file)
    f.close()

    
def update_tokencc():
    """ Update the following check in the tokencc file:-
    From:
  ASSERT(ARRAY_SIZE(keyword) == 25 + 3 + 3 + 1);  // +1 for ILLEGAL sentinel
    To:
  ASSERT(ARRAY_SIZE(keyword) == 25 + 3 + 3 + 1 + 2);   // +1 for ILLEGAL sentinel, +2 for Z:
  
    Note: the '+ 2' is dynamically generated depend on the num of new zed tokens
    """
    
    # get the number of new zed tokens
    num_z_tokens = str(len(tokens))
    
    # filename
    s_filename = "token.cc"
    
    # read the file
    f = open(zutil.get_read_path(s_filename))
    s_file = f.read() 
    f.close()
    #print(s_file)

    # Update the ASSERT keyword check to include new zed tokens
    p = re.compile(r"^(.*ASSERT\(ARRAY_SIZE.*)(\)\;)(.*sentinel.*$)", re.MULTILINE)
    m = p.search(s_file)
    if not m:
        raise Exception("token.cc: No match for ASSERT ARRAY_SIZE macro found")
    #print m
    #print m.group()
    #print m.group(1)
    # Create a string 'zmsg' to append to the ASSERT comment to indicate the ASSERT has been updated
    zmsg = ", +" + num_z_tokens + " for Z:"
    s_file = p.sub(r"\1 + " + num_z_tokens + r"\2 \3" + zmsg, s_file)   
    #print m.group(3)
    
    # write the file
    f = open(zutil.get_write_path(s_filename), "w")
    f.write(s_file)
    f.close()

    
# main function
def main():
    update_tokenh()
    update_tokencc()


# call the main function
if __name__ == "__main__":
    main()

